package com.mvc.anocation.servlet;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ActionServlet extends HttpServlet {

	private static final long serialVersionUID = 2411155147670549404L;

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String path = this.getPath(request.getServletPath());
		System.out.println(path);
		Map<String, String> map = (Map<String, String>) this.getServletContext().getAttribute("s");
		String value = map.get(path);
		String[] values = value.split("\\|\\|");
		String className = values[0];
		String methodName = values[1];
		String[] parameterName = values[2].split(",");
		// 初始化反射执行方法所需的参数数组
		Class<?>[] paras = new Class[parameterName.length];
		for (int i = 0; i < parameterName.length; i++) {
			try {
				// 给反射执行方法所需的参数数组赋值
				paras[i] = Class.forName(parameterName[i]);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
		Object objAction;
		Class<?> clazz;
		Object rs = null;
		try {
			// 反射action
			clazz = Class.forName(className);
			objAction = clazz.newInstance();
			// 获取action中对应的方法
			Method method = clazz.getDeclaredMethod(methodName, paras);
			Object[] parasInstaces = new Object[paras.length];
			// 给反射的参数对象循环赋值
			for (int i = 0; i < paras.length; i++) {
				Object paraInstance = null;

				if (paras[i].isInterface()) {
					if (paras[i].getName().equals("javax.servlet.http.HttpServletRequest")) {
						paraInstance = request;
					} else if (paras[i].getName().equals("javax.servlet.http.HttpServletResponse")) {
						paraInstance = response;
					}
				} else {
					paraInstance = (Object) paras[i].newInstance();
					Field[] fields = paras[i].getDeclaredFields();
					for (Field f : fields) {
						f.setAccessible(true);
						f.set(paraInstance, request.getParameter(f.getName()));
						f.setAccessible(false);
					}
				}
				parasInstaces[i] = paraInstance;
			}
			// 调用action中对应的方法
			rs = method.invoke(objAction, parasInstaces);
		} catch (Exception e) {
			e.printStackTrace();
		}
		RequestDispatcher dis = request.getRequestDispatcher(rs.toString());
		dis.forward(request, response);
	}

	private String getPath(String servletPath) {
		return servletPath.split("\\.")[0];
	}
}
